package ar.uba.is2.ec.config;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.log4j.Logger;

import ar.uba.is2.common.loc.Coordenada;
import ar.uba.is2.common.mensaje.contenido.Identificador;
import ar.uba.is2.common.mensaje.contenido.TipoDato;
import ar.uba.is2.ec.matem.modelo.ModeloMatematico;
import ar.uba.is2.ec.matem.motor.Regla;
import ar.uba.is2.ec.matem.motor.impl.ReglaAbstracta;

public class ModeloMatematicoFactory {
	
	private static final Logger logger = Logger.getLogger(ModeloMatematicoFactory.class);
	
	public static final ModeloMatematicoFactory instance = new ModeloMatematicoFactory();
	
	public static final Coordenada coordenada = new Coordenada(01.11, 19.83);

	private static final int MAXIMO_DATO = 5;

	public Collection<ModeloMatematico> obtenerModelos() {
		
		String stringModelos = Contexto.instance.get("ec.modelos.matematicos.ids");
		
		String[] modelosIds = stringModelos.split(",");
		
		Collection<ModeloMatematico> modelos  = new ArrayList<ModeloMatematico>();
		for (String idModelo : modelosIds) {
			ModeloMatematico modelo = construirModelo(idModelo);
			modelos.add(modelo);
		}
		
		return modelos;
	}

	private ModeloMatematico construirModelo(String idModelo) {

		ModeloMatematico modelo = new ModeloMatematico(idModelo);
		
		String stringReglas = Contexto.instance.get(String.format("ec.modelos.matematicos.%s.reglas", idModelo));
		String[] reglasIds = stringReglas.split(",");
		
		for (String idRegla : reglasIds) {
			Regla regla = construirRegla(idModelo, idRegla);
			
			modelo.agregarRegla(regla);
		}
		
		return modelo;
	}

	@SuppressWarnings("unchecked")
	private Regla construirRegla(String idModelo, String idRegla) {

		String stringClaseRegla = Contexto.instance.get(String.format("ec.modelos.matematicos.%s.reglas.%s.clase", idModelo, idRegla));

		Class<ReglaAbstracta> claseRegla;
		try {
			claseRegla = (Class<ReglaAbstracta>) Class.forName(stringClaseRegla);
		
			ReglaAbstracta regla = claseRegla.newInstance();
			
			for (int i = 1; i <= MAXIMO_DATO; i++){
				Identificador id = construirDatoRequerido(idModelo, idRegla, i);
				
				if (id != null) {
					regla.addDatoRequerido(id);
				}
			}
			
			return regla;
		} catch (Exception e) {
			logger.error("Error instanciando regla " + idModelo + " " + idRegla, e);
		}

		return null;
	}

	private Identificador construirDatoRequerido(String idModelo,
			String idRegla, int i) {
		
		String stringDatoRequerido = Contexto.instance.get(String.format("ec.modelos.matematicos.%s.reglas.%s.dato%s", idModelo, idRegla, i));
		if (stringDatoRequerido.length() > 0) {
			String[] splitDatos = stringDatoRequerido.split(",");
			
			TipoDato tipoDato = TipoDato.valueOf(splitDatos[0]);
			
			double latitud = Double.parseDouble(splitDatos[1]);
			double longitud = Double.parseDouble(splitDatos[2]);
			
			String valorIdentificador = splitDatos[3];
			
			Identificador identificador = new Identificador(tipoDato, new Coordenada(latitud, longitud), valorIdentificador);
			
			if (logger.isDebugEnabled()) {
				logger.debug(String.format("Identificador %s creado para el modelo %s y regla %s", identificador, idModelo, idRegla));
			}
			
			return identificador;
		}
		
		return null;
	}

}
